package com.spring.factory;

import com.spring.annotation.Service;
import com.spring.bean.BeanDefinition;
import com.spring.utils.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

/**
 * @author SpringWang
 * @date 2021/6/2
 */
public class BeanDefinitionReader {

    private final Properties contextConfig = new Properties();

    private final List<String> beanRegistryClasses = new ArrayList<>();

    public BeanDefinitionReader(String... configLocations) {
        // 加载配置文件
        loadConfig(configLocations[0]);
        // 扫描相关类
        scan(contextConfig.getProperty("scanPackage"));
    }

    private void loadConfig(String configLocation) {
        InputStream inputStream = BeanDefinitionReader.class.getClassLoader().getResourceAsStream(configLocation);
        try {
            contextConfig.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void scan(String scanPackage) {
        // 获取根目录，拿到com.spring转换成com/spring
        URL url = BeanDefinitionReader.class.getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        assert url != null;
        File classFile = new File(url.getFile());
        for (File file : Objects.requireNonNull(classFile.listFiles())) {
            // 如果是文件夹，则递归往下扫描
            if (file.isDirectory()) {
                scan(scanPackage + "." + file.getName());
            } else {
                // 如果不是.class文件则跳过
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = (scanPackage + "." + file.getName()).replace(".class", "");
                // 类全限定名放入集合中，方便实例化
                beanRegistryClasses.add(className);
            }
        }
    }

    public List<BeanDefinition> loadBeanDefinitions() {
        ArrayList<BeanDefinition> beanDefinitions = new ArrayList<>();
        for (String registryClass : beanRegistryClasses) {
            try {
                Class<?> beanClass = Class.forName(registryClass);
                // 1.忽略加注解的接口
                // 2.只有加了自定义注解的才需要注入，没加的忽略
                if (beanClass.isInterface() || beanClass.isAnnotationPresent(Service.class)) {
                    continue;
                }
                String beanName = beanClass.getAnnotation(Service.class).value();
                if ("".equals(beanName)) {
                    beanName = StringUtils.toLowerFirstCase(beanClass.getSimpleName());
                }
                beanDefinitions.add(BeanDefinition.create(beanName, beanClass.getName()));
                // 处理实现接口
                for (Class<?> i : beanClass.getInterfaces()) {
                    beanDefinitions.add(BeanDefinition.create(i.getName(), beanClass.getName()));
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return beanDefinitions;
    }

    public Properties getConfig() {
        return contextConfig;
    }
}
